package com.ruoyi.web.core.config;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.web.controller.common.CommonController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @ProjectName: ruoyi
 * @ClassName: WebSocket
 * @Description:
 * @Author: @Abeiv
 * @Date: 2020-2-26 17:22
 */
@Component
@ServerEndpoint("/websocket/{name}")
public class WebSocket {

    /**
     * 与某个客户端的连接对话，需要通过它来给客户端发送消息
     */
    private Session session;


    /**
     * 用于存所有的连接服务的客户端，这个对象存储是安全的
     */
    private static final Map<Integer, CopyOnWriteArraySet<WebSocket>> rooms = new HashMap<>();
    /**
     * 标识当前连接客户端的用户名
     */
    private Integer userId;
    /**
     * 分组id
     */
    private Integer roomId;

    private static final Logger log = LoggerFactory.getLogger(CommonController.class);

    @OnOpen
    public void OnOpen(Session session, @PathParam(value = "name") String name) {
        this.session = session;
        session.setMaxIdleTimeout(1 * 60 * 60 * 24 * 30);
        String[] param = name.split("-");
        this.roomId = Integer.parseInt(param[0]);
        this.userId = Integer.parseInt(param[1]);
        CopyOnWriteArraySet<WebSocket> friends = rooms.get(roomId);
        if (friends == null) {
            synchronized (rooms) {
                // 如果没有该分组则新建
                if (!rooms.containsKey(roomId)) {
                    friends = new CopyOnWriteArraySet<>();
                    rooms.put(roomId, friends);
                    log.info("[WebSocket] {}分组创建成功，当前分组数为：={}", roomId, rooms.size());
                }
            }
        }
        friends.add(this);
        log.info("[WebSocket] {}成功连接到{}分组，当前连接人数为：={}", userId, roomId, friends.size());
    }


    @OnClose
    public void OnClose() {
        CopyOnWriteArraySet<WebSocket> friends = rooms.get(roomId);
        if (friends != null) {
            friends.remove(this);
            log.info("[WebSocket] 退出成功，当前{}分组连接人数为：={}", roomId, friends.size());
        }
    }

    @OnMessage
    public void OnMessage(String message) {
        log.info("[WebSocket] 收到消息：{}", message);
        //判断是否需要指定发送，具体规则自定义
        if (message.indexOf("TOUSER") == 0) {
            String name = message.substring(message.indexOf("TOUSER") + 6, message.indexOf(";"));
            AppointSending(name, message.substring(message.indexOf(";") + 1, message.length()));
        } else {
            GroupSending(message, roomId);
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.info("发生错误" + new Date());
        error.printStackTrace();
    }

    /**
     * 群发
     *
     * @param message
     */
    public static void GroupSending(String message, Integer roomId) {
        CopyOnWriteArraySet<WebSocket> friends = rooms.get(roomId);
        if (friends != null) {
            int inedx = 0;
            for (WebSocket item : friends) {
                inedx++;
                item.session.getAsyncRemote().sendText(message);
            }
            log.info("{}分组群发消息成功：{}， 时间：{}, 发送条数为：{}", roomId, message, DateUtils.getNowDate(), inedx);
        }else {
            log.info("{}分组群发消息失败：{}， 时间：{}, error：{}", roomId, message, DateUtils.getNowDate(), "没有该分组");
        }
    }

    /**
     * 指定发送
     *
     * @param name
     * @param message
     */
    public static void AppointSending(String name, String message) {
        String[] param = name.split("-");
        Integer roomId = Integer.parseInt(param[0]);
        Integer userId = Integer.parseInt(param[1]);
        CopyOnWriteArraySet<WebSocket> friends = rooms.get(roomId);
        if (friends != null) {
            boolean isSend = false;
            for (WebSocket item : friends) {
                if (item.userId == userId) {
                    isSend = true;
                    item.session.getAsyncRemote().sendText(message);
                    log.info("{}分组发送消息成功：{}， 时间：{}, 发送对象：{}", roomId, message, DateUtils.getNowDate(), item.userId);
                    break;
                }
            }
            if(!isSend){
                log.info("{}分组指定发送消息失败：{}， 时间：{}, error：{}", roomId, message, DateUtils.getNowDate(), "该用户未在线");
            }
        }else {
            log.info("{}分组指定发送消息失败：{}， 时间：{}, error：{}", roomId, message, DateUtils.getNowDate(), "没有该分组");
        }
    }
}